"""
Seaborn 时间序列可视化示例

知识点：
1. 时间序列折线图基础
2. 多条时间序列对比
3. 置信区间和误差带
4. 时间序列分解展示
5. 滚动平均和趋势线
"""

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 先设置 seaborn 主题
sns.set_theme(style="darkgrid")

# 然后强制设置中文字体（必须在 set_theme 之后）
plt.rcParams['font.sans-serif'] = ['PingFang HK', 'Hiragino Sans GB', 'STHeiti', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'

# 创建时间序列数据
np.random.seed(42)
dates = pd.date_range('2023-01-01', periods=365, freq='D')
products = ['产品A', '产品B', '产品C']

data_list = []
for product in products:
    base = 100 + np.random.randint(0, 50)
    trend = np.linspace(0, 30, 365)
    seasonal = 20 * np.sin(np.linspace(0, 4*np.pi, 365))
    noise = np.random.normal(0, 8, 365)
    sales = base + trend + seasonal + noise
    
    for i, date in enumerate(dates):
        data_list.append({
            '日期': date,
            '销售额': sales[i],
            '产品': product
        })

df = pd.DataFrame(data_list)

fig, axes = plt.subplots(2, 2, figsize=(16, 10))
fig.suptitle('时间序列可视化技术', fontsize=16, fontweight='bold')

# 1. 基础时间序列
sns.lineplot(data=df, x='日期', y='销售额', hue='产品', ax=axes[0, 0])
axes[0, 0].set_title('1. 基础时间序列')
axes[0, 0].tick_params(axis='x', rotation=45)

# 2. 带置信区间
sns.lineplot(data=df, x='日期', y='销售额', hue='产品', ci=95, ax=axes[0, 1])
axes[0, 1].set_title('2. 95%置信区间')
axes[0, 1].tick_params(axis='x', rotation=45)

# 3. 月度聚合
monthly = df.groupby([pd.Grouper(key='日期', freq='M'), '产品'])['销售额'].mean().reset_index()
sns.lineplot(data=monthly, x='日期', y='销售额', hue='产品', markers=True, ax=axes[1, 0])
axes[1, 0].set_title('3. 月度平均值')
axes[1, 0].tick_params(axis='x', rotation=45)

# 4. 滚动平均
df_sorted = df.sort_values('日期')
for product in products:
    product_data = df_sorted[df_sorted['产品'] == product].copy()
    product_data['滚动平均'] = product_data['销售额'].rolling(window=30).mean()
    axes[1, 1].plot(product_data['日期'], product_data['滚动平均'], label=product, linewidth=2)

axes[1, 1].set_title('4. 30天滚动平均')
axes[1, 1].legend()
axes[1, 1].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/7-时间序列.png', 
            dpi=300, bbox_inches='tight')
plt.show()
